using System;
using System.Collections.Generic;

namespace MediaBridge
{
    /// <summary>
    /// Holds data that is sent from the source filter
    /// </summary>
    public class MediaBridgeGraphInfo
    {
        /// <summary>
        /// The media url sent from the WPF application, 
        /// recieved by the filter
        /// </summary>
        private string _mediaUrl;
        
        /// <summary>
        /// Pointer to the filter's graph
        /// </summary>
        private IntPtr _pFilterGraph;

        /// <summary>
        /// Pointer to the source filter
        /// </summary>
        private IntPtr _pSourceFilter;

        /// <summary>
        /// Success flag
        /// </summary>
        private bool _success = false;

        /// <summary>
        /// The media url sent from the WPF application, 
        /// recieved by the filter
        /// </summary>
        public string MediaUrl
        {
            get{return _mediaUrl;}
            set{_mediaUrl = value;}
        }

        /// <summary> 
        /// Pointer to the filter's graph
        /// </summary>
        public IntPtr FilterGraph
        {
            get { return _pFilterGraph; }
            set{_pFilterGraph = value;}
        }

        /// <summary>
        /// Pointer to the source filter
        /// </summary>
        public IntPtr SourceFilter
        {
            get { return _pSourceFilter; }
            set { _pSourceFilter = value; }
        }

        /// <summary>
        /// Success flag
        /// </summary>
        public bool Success
        {
            get { return _success; }
            set { _success = value; }
        }
    }

    /// <summary>
    /// Handles delegation of callbacks from source filters
    /// </summary>
    public class MediaBridgeManager
    {
        public delegate void NewMediaGraphInfo(MediaBridgeGraphInfo GraphInfo);

        /// <summary>
        /// Used to store a hash of media Url keys and delegate callbacks
        /// </summary>
        private static readonly Dictionary<string, NewMediaGraphInfo> _delegateHash = new Dictionary<string, NewMediaGraphInfo>();

        /// <summary>
        /// Formats the media Url to match any mangling DirectShow does to the Url.
        /// </summary>
        /// <param name="Url">The Url to format.</param>
        /// <returns>Returns a formatted Url</returns>
        private static string FormatUrl(string Url)
        {
            Url = Url.ToLower();
            Url += "/";

            return Url;
        }

        /// <summary>
        /// Adds graph information and does the correct callback
        /// </summary>
        /// <param name="GraphInfo">The information passed from the filter</param>
        public static void AddMediaGraphInfo(MediaBridgeGraphInfo GraphInfo)
        {
            if (_delegateHash.ContainsKey(GraphInfo.MediaUrl))
            {
                NewMediaGraphInfo callback = _delegateHash[GraphInfo.MediaUrl];
                _delegateHash.Remove(GraphInfo.MediaUrl);

                /* Suppress all errors on the callback */
                try
                {
                    callback(GraphInfo);
                }
                catch{}
            }
        }

        /// <summary>
        /// Removes the delegate callback that was registered
        /// </summary>
        /// <param name="MediaUrl">The unique media Url that is used as a key</param>
        public static void UnregisterCallback(string MediaUrl)
        {
            MediaUrl = FormatUrl(MediaUrl);
            if (_delegateHash.ContainsKey(MediaUrl))
            {
                _delegateHash.Remove(MediaUrl);
            }
        }

        /// <summary>
        /// Registers a callback for the filter to execute
        /// </summary>
        /// <param name="MediaUrl">The unique Url used as a key</param>
        /// <param name="Callback">A delegate to callback</param>
        /// <returns>Returns true if the registration of the callback was successful, otherwise false</returns>
        public static bool RegisterCallback(string MediaUrl, NewMediaGraphInfo Callback)
        {
            MediaUrl = FormatUrl(MediaUrl);

            if (_delegateHash.ContainsKey(MediaUrl)) 
                return false;
            
            _delegateHash.Add(MediaUrl, Callback);

            return true;
        }
    }
}
